﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using log4net;

namespace PES.Common.DAL
{
    using Model;

    internal class CampeonatoDAL
    {
        private static ILog s_logger;
        private static ILog Logger
        {
            get { return s_logger ?? (s_logger = LogManager.GetLogger("CampeonatoDAL")); }
        }

        public void CadastraCampeonato(Campeonato _campeonato)
        {
            Database db = DatabaseFactory.CreateDatabase(DbHelper.PES_DATABASE);

            using (DbConnection connection = db.CreateConnection())
            {
                connection.Open();
                DbTransaction transaction = connection.BeginTransaction();
                try
                {
                    string nomeParameter = db.BuildParameterName("NomeCamp");
                    string dataIniParameter = db.BuildParameterName("DataIni");
                    string estiloParameter = db.BuildParameterName("EstiloCamp");
                    string finalizadoParameter = db.BuildParameterName("Finalizado");
                    string tipoFinaisParameter = db.BuildParameterName("TipoFinais");
                    string qtdeRebaixamentoParameter = db.BuildParameterName("QtdeReb");

                    string sql =
                        string.Format(
                            @"INSERT INTO Campeonato (nome, data_inicio, estilo_campeonato, finalizado, qtde_times_finalistas, qtde_times_rebaixados) VALUES ({0}, {1}, {2}, {3}, {4}, {5})",
                            nomeParameter, dataIniParameter, estiloParameter, finalizadoParameter, tipoFinaisParameter,
                            qtdeRebaixamentoParameter);

                    DbCommand cmd = db.GetSqlStringCommand(sql);
                    db.AddInParameter(cmd, nomeParameter, DbType.String, _campeonato.Nome);
                    db.AddInParameter(cmd, dataIniParameter, DbType.DateTime, _campeonato.DataInicio.Date);
                    db.AddInParameter(cmd, estiloParameter, DbType.Int16, (short) _campeonato.EstiloCampeonato);
                    db.AddInParameter(cmd, finalizadoParameter, DbType.Boolean, _campeonato.Finalizado);
                    if (_campeonato.EstiloCampeonato == TipoCampeonato.PONTOS_CORRIDOS_UM_TURNO_COM_FINAIS ||
                        _campeonato.EstiloCampeonato == TipoCampeonato.PONTOS_CORRIDOS_DOIS_TURNOS_COM_FINAIS)
                    {
                        db.AddInParameter(cmd, tipoFinaisParameter, DbType.Int16,
                                          (short) _campeonato.QtdeTimesClassificadosFinais);
                    }
                    else
                    {
                        db.AddInParameter(cmd, tipoFinaisParameter, DbType.Int16, null);
                    }

                    db.AddInParameter(cmd, qtdeRebaixamentoParameter, DbType.Int16, _campeonato.QtdeTimesRebaixados);

                    db.ExecuteNonQuery(cmd, transaction);

                    sql = @"SELECT @@IDENTITY Campeonato";
                    cmd = db.GetSqlStringCommand(sql);
                    _campeonato.ID = Convert.ToInt32(db.ExecuteScalar(cmd, transaction));

                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    Logger.Error("Ocorreu um erro ao salvar o campeonato.", ex);
                    transaction.Rollback();
                    throw;
                }
                finally
                {
                    connection.Close();
                }
            }
        }

        public bool ExisteCampeonato(string _nome)
        {
            Database db = DatabaseFactory.CreateDatabase(DbHelper.PES_DATABASE);
            string nomeParam = db.BuildParameterName("NomeCamp");
            DbCommand cmd = db.GetSqlStringCommand(
                string.Format("SELECT COUNT(*) FROM Campeonato WHERE nome = {0}", nomeParam));
            db.AddInParameter(cmd, nomeParam, DbType.String, _nome);
            int count = Convert.ToInt32(db.ExecuteScalar(cmd));
            return count > 0;
        }

        public void FinalizarCampeonato(int _campeonatoID)
        {
            Database db = DatabaseFactory.CreateDatabase(DbHelper.PES_DATABASE);
            string campIDParameter = db.BuildParameterName("campID");
            string sql = @"UPDATE Campeonato SET finalizado = true WHERE campeonato_id = {0}";
            sql = string.Format(sql, campIDParameter);
            DbCommand cmd = db.GetSqlStringCommand(sql);
            db.AddInParameter(cmd, campIDParameter, DbType.Int32, _campeonatoID);
            db.ExecuteNonQuery(cmd);
        }

        public IList<Campeonato> BuscarTodosCampeonatos(bool _buscarTodos, bool _finalizado)
        {
            Database db = DatabaseFactory.CreateDatabase(DbHelper.PES_DATABASE);
            string sql = @"SELECT 
                            C.campeonato_id, 
                            C.nome, 
                            C.data_inicio, 
                            C.estilo_campeonato, 
                            C.data_fim, 
                            C.finalizado, 
                            C.controlar_cartoes, 
                            C.qtde_rodadas,
                            C.qtde_times_finalistas,
                            C.qtde_times_rebaixados
                        FROM 
                            Campeonato C ";

            if (!_buscarTodos)
            {
                if (_finalizado)
                {
                    sql += " WHERE C.finalizado = 1";
                }
                else
                {
                    sql += " WHERE finalizado = 0";
                }

            }

            DbCommand cmd = db.GetSqlStringCommand(sql);

            var lstCampeonatos = new List<Campeonato>();

            using (IDataReader dbReader = db.ExecuteReader(cmd))
            {
                while (dbReader.Read())
                {
                    var camp = new Campeonato
                        {
                            ID = dbReader.GetInt32(0),
                            Nome = dbReader.GetString(1),
                            DataInicio = dbReader.GetDateTime(2),
                            EstiloCampeonato = (TipoCampeonato) dbReader.GetInt16(3)
                        };

                    if (!dbReader.IsDBNull(4))
                    {
                        camp.DataFim = dbReader.GetDateTime(4);
                    }
                    
                    camp.Finalizado = dbReader.GetBoolean(5);
                   
                    camp.ControlarCartaoJogadores = dbReader.GetBoolean(6);
                    if (!dbReader.IsDBNull(7))
                    {
                        camp.QuantidadeRodadas = dbReader.GetInt32(7);
                    }

                    if (!dbReader.IsDBNull(8))
                    {
                        camp.QtdeTimesClassificadosFinais = (TipoFinaisPontosCorridos) dbReader.GetInt16(8);
                    }

                    if (!dbReader.IsDBNull(9))
                    {
                        camp.QtdeTimesRebaixados = dbReader.GetInt16(9);
                    }

                    lstCampeonatos.Add(camp);
                }
            }

            return lstCampeonatos;
        }

        public IList<Jogador> BuscarRankingCampeonato(int _campeonatoID)
        {
            Database db = DatabaseFactory.CreateDatabase(DbHelper.PES_DATABASE);
            string sql = @"SELECT
                                J.jogador_id, 
                                J.nome,
                                J.time_escolhido,
                                P.pontuacao_id,
                                P.pontos, 
                                P.num_vitorias, 
                                P.num_empates, 
                                P.num_derrotas, 
                                P.gols_pro, 
                                P.gols_contra,
                                (P.gols_pro - P.gols_contra) AS saldo_gols 
                           FROM
                                Campeonato_Jogadores CJ,
                                Campeonato C,
                                Jogador J
                                LEFT JOIN Pontuacao P ON
                                                        (J.pontuacao_id = P.pontuacao_id)
                           WHERE
                                CJ.campeonato_id = {0} AND
                                CJ.jogador_id = J.jogador_id AND
                                C.campeonato_id = CJ.campeonato_id                              
                           ORDER BY
                                P.pontos DESC, P.num_vitorias DESC, saldo_gols DESC, P.gols_pro DESC, P.gols_contra ASC, P.num_empates ASC, P.num_derrotas ASC, J.nome ASC";

            string campIDParameter = db.BuildParameterName("campID");
            sql = string.Format(sql, campIDParameter);

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, campIDParameter, DbType.Int32, _campeonatoID);

            var lstJogadores = new List<Jogador>();

            using (IDataReader dbReader = db.ExecuteReader(cmd))
            {
                while (dbReader.Read())
                {
                    var j = new Jogador
                        {
                            ID = dbReader.GetInt64(0),
                            Nome = dbReader.GetString(1),
                            TimeEscolhido = dbReader.GetString(2)
                        };
                    if (!dbReader.IsDBNull(3))
                    {
                        j.Pontos = new Pontuacao
                            {
                                ID = dbReader.GetInt64(3),
                                TotalPontos = dbReader.GetInt32(4),
                                NumVitorias = dbReader.GetInt32(5),
                                NumEmpates = dbReader.GetInt32(6),
                                NumDerrotas = dbReader.GetInt32(7),
                                GolsPro = dbReader.GetInt32(8),
                                GolsContra = dbReader.GetInt32(9)
                            };
                    }

                    lstJogadores.Add(j);
                }
            }

            return lstJogadores;
        }

        public Campeonato BuscarCampeonato(int _campeonatoID)
        {
            Database db = DatabaseFactory.CreateDatabase(DbHelper.PES_DATABASE);
            string sql = @"SELECT 
                            C.campeonato_id, 
                            C.nome, 
                            C.data_inicio, 
                            C.estilo_campeonato, 
                            C.data_fim, 
                            C.finalizado, 
                            C.controlar_cartoes, 
                            C.qtde_rodadas,
                            C.qtde_times_finalistas,
                            C.qtde_times_rebaixados 
                        FROM 
                            Campeonato C
                        WHERE 
                            C.campeonato_id = {0}";

            string campIDParam = db.BuildParameterName("CampID");
            sql = string.Format(sql, campIDParam);

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, campIDParam, DbType.Int32, _campeonatoID);

            Campeonato camp = null;

            using (IDataReader dbReader = db.ExecuteReader(cmd))
            {
                while (dbReader.Read())
                {
                    camp = new Campeonato
                        {
                            ID = dbReader.GetInt32(0),
                            Nome = dbReader.GetString(1),
                            DataInicio = dbReader.GetDateTime(2),
                            EstiloCampeonato = (TipoCampeonato) dbReader.GetInt16(3)
                        };
                    if (!dbReader.IsDBNull(4))
                    {
                        camp.DataFim = dbReader.GetDateTime(4);
                    }
                    camp.Finalizado = dbReader.GetBoolean(5);
                    
                    camp.ControlarCartaoJogadores = dbReader.GetBoolean(6);
                    if (!dbReader.IsDBNull(7))
                    {
                        camp.QuantidadeRodadas = dbReader.GetInt32(7);
                    }

                    if (!dbReader.IsDBNull(8))
                    {
                        camp.QtdeTimesClassificadosFinais = (TipoFinaisPontosCorridos) dbReader.GetInt16(8);
                    }

                    if (!dbReader.IsDBNull(9))
                    {
                        camp.QtdeTimesRebaixados = dbReader.GetInt16(9);
                    }
                }
            }

            return camp;
        }

        public void AtualizaQuantidadeRodadas(int _campID, int _qtdeJogos)
        {
            Database db = DatabaseFactory.CreateDatabase(DbHelper.PES_DATABASE);
            string sql = "UPDATE Campeonato SET qtde_rodadas = {0} WHERE campeonato_id = {1}";
            var parametros = new[]
                {
                    db.BuildParameterName("QtdRod"),
                    db.BuildParameterName("CampID")
                };

            sql = string.Format(sql, parametros);

            DbCommand cmd = db.GetSqlStringCommand(sql);
            db.AddInParameter(cmd, parametros[0], DbType.Int32, _qtdeJogos);
            db.AddInParameter(cmd, parametros[1], DbType.Int32, _campID);

            db.ExecuteNonQuery(cmd);
        }
    }
}
